<template>
  <van-form ref="formRef" @submit="onSubmit">
    <template v-for="field in props.config" :key="field.prop">
      <component
        :is="getComponentByType(field.type)"
        :field="field"
        v-model="formData[field.prop]"
        :options="getFieldOptions(field)"
      />
    </template>

    <!-- 提交按钮 -->
    <div style="margin: 16px">
      <van-button round block type="primary" native-type="submit">
        {{ submitText }}
      </van-button>
    </div>
  </van-form>
</template>

<script setup>
import { ref, reactive, watch, onMounted, onUnmounted } from "vue";
import { showToast } from "vant";
import request from "../utils/request";

// 导入表单项组件
import InputField from "./form-items/InputField.vue";
import TextareaField from "./form-items/TextareaField.vue";
import RadioField from "./form-items/RadioField.vue";
import CheckboxField from "./form-items/CheckboxField.vue";
import SelectField from "./form-items/SelectField.vue";
import CustomField from "./form-items/CustomField.vue";

const props = defineProps({
  config: {
    type: Array,
    required: true,
    validator: (value) =>
      value.every(
        (item) =>
          item.type &&
          item.prop &&
          item.label &&
          (item.type !== "custom" || typeof item.render === "function")
      ),
  },
  submitText: {
    type: String,
    default: "提交",
  },
  modelValue: {
    type: Object,
    default: () => ({}),
  },
});

const emit = defineEmits(["update:modelValue", "submit", "validate"]);

const formRef = ref(null);
const formData = reactive({});
const dynamicOptions = reactive({});

// 根据类型获取对应的组件
const getComponentByType = (type) => {
  const componentMap = {
    input: InputField,
    textarea: TextareaField,
    radio: RadioField,
    checkbox: CheckboxField,
    select: SelectField,
    custom: CustomField,
  };
  return componentMap[type] || InputField;
};

// 监听表单数据变化
watch(
  formData,
  (newVal) => {
    emit("update:modelValue", newVal);
  },
  { deep: true }
);

// 初始化表单数据
const initFormData = () => {
  props.config.forEach((field) => {
    formData[field.prop] =
      props.modelValue[field.prop] ||
      field.defaultValue ||
      (field.type === "checkbox" ? [] : "");
  });
};

// 表单验证方法
const validate = async () => {
  if (!formRef.value) return false;
  try {
    await formRef.value.validate();
    return true;
  } catch {
    return false;
  }
};

// 重置表单
const resetForm = () => {
  formRef.value?.resetValidation();
  initFormData();
};

// 获取字段的选项数据
const getFieldOptions = (field) =>
  field?.options || dynamicOptions[field?.prop] || [];

// 提交表单
const onSubmit = async () => {
  const isValid = await validate();
  emit("validate", isValid);
  if (isValid) {
    emit("submit", formData);
  }
};

// 加载选项数据
const loadFieldOptions = async (field) => {
  if (!field?.optionsUrl && !field?.options) {
    console.warn(`字段 ${field?.prop} 未配置数据源`);
    return;
  }

  try {
    if (field.optionsUrl) {
      const { data } = await request({
        url: field.optionsUrl,
        method: field.method || "GET",
        params: field.params,
        data: field.data,
      });
      dynamicOptions[field.prop] = field.formatOptions
        ? field.formatOptions(data)
        : data;
    } else {
      dynamicOptions[field.prop] = field.options;
    }
  } catch (error) {
    console.error(`加载选项数据失败: ${error}`);
    showToast("加载选项数据失败");
    dynamicOptions[field.prop] = [];
  }
};

// 初始化所有字段的选项数据
const initFieldsOptions = async () => {
  const optionsFields = props.config.filter((field) =>
    ["select", "radio", "checkbox"].includes(field.type)
  );
  for (const field of optionsFields) {
    await loadFieldOptions(field);
  }
};

// 清理函数
const cleanup = () => {
  Object.keys(dynamicOptions).forEach((key) => delete dynamicOptions[key]);
};

// 生命周期钩子
onMounted(() => {
  initFormData();
  initFieldsOptions();
});

onUnmounted(() => {
  cleanup();
});

// 对外暴露方法
defineExpose({
  validate,
  resetForm,
  formData,
});
</script>
